package com.zbkj.service.service.course.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.zbkj.common.constants.IntegralRecordConstants;
import com.zbkj.common.model.course.Activity;
import com.zbkj.common.model.course.ActivityLog;
import com.zbkj.common.model.course.UserTaskLog;
import com.zbkj.common.model.user.User;
import com.zbkj.common.model.user.UserIntegralRecord;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.course.ActivityLogSearchRequest;
import com.zbkj.common.request.course.QRCodeSweepRequest;
import com.zbkj.service.dao.ActivityLogDao;
import com.zbkj.service.service.UserIntegralRecordService;
import com.zbkj.service.service.UserService;
import com.zbkj.service.service.course.ActivityLogService;
import com.zbkj.service.service.course.ActivityService;
import lombok.extern.slf4j.Slf4j;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Mr.guqianbin
 * @description ActivityLogServiceImpl 接口实现
 * @date 2022-08-31
 */
@Service
@Slf4j
public class ActivityLogServiceImpl extends ServiceImpl<ActivityLogDao, ActivityLog> implements ActivityLogService {

    @Resource
    private ActivityLogDao dao;

    @Autowired
    private ActivityService activityService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserIntegralRecordService integralRecordService;

    /**
     * 列表
     *
     * @param request          请求参数
     * @param pageParamRequest 分页类参数
     * @return List<ActivityLog>
     * @author Mr.guqianbin
     * @since 2022-08-31
     */
    @Override
    public List<ActivityLog> getList(ActivityLogSearchRequest request, PageParamRequest pageParamRequest) {
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

        //带 ActivityLog 类的多条件查询
        LambdaQueryWrapper<ActivityLog> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(ObjectUtil.isNotEmpty(request.getActivityId())&&request.getActivityId()>0){
            lambdaQueryWrapper.eq(ActivityLog::getActivityId,request.getActivityId());
        }
        return dao.selectList(lambdaQueryWrapper);
    }


    /**
     * 活动二维码签到
     *
     * @return
     */
    @Override
    @Transactional
    public Map<String, Object> activitySign(QRCodeSweepRequest request) {
        log.info(request.toString());
        //todo 增加经纬度、计算距离
        Map<String, Object> data = new HashMap<>();
        LambdaQueryWrapper<Activity> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Activity::getCode, request.getQrCodeStr());
        List<Activity> activities = activityService.list(lqw);
        if (CollectionUtil.isEmpty(activities)) {
            data.put("message", "没有该活动");
            data.put("success", false);
            log.info("没有该活动");
            return data;
        }
        Activity activity = activities.get(0);
        Date beginDate = activity.getBeginDate();
        Date endDate = activity.getEndDate();
        Date now = new Date();
        if (now.compareTo(beginDate) < 0 || now.compareTo(endDate) > 0) {
            data.put("success", false);
            data.put("message", "还未到签到时间");
            log.info("没有该活动");

            return data;
        }

        User user = userService.getInfoException();

        if (isSign(activity, user)) {
            data.put("success", false);
            data.put("message", "您已完成签到");
            log.info("您已完成签到");

            return data;
        }
        if(ObjectUtil.isEmpty(request.getLatitude())
                ||ObjectUtil.isEmpty(request.getLongitude())){
            data.put("success", false);
            data.put("message", "请打开定位");
            log.info("请打开定位");

            return data;
        }
        Double distance = getDistance(request.getLatitude(), request.getLongitude()
                , activity.getLatitude(), activity.getLongitude());
        if(distance.compareTo(activity.getDistance().doubleValue())>0){
            data.put("success", false);
            data.put("message", "您签到距离较远，请打开定位");
            log.info("您签到距离较远，请打开定位");
            return data;
        }
        ActivityLog activityLog = new ActivityLog();
        activityLog.setUid(user.getUid());
        activityLog.setActivityId(activity.getId());
        activityLog.setCreateTime(new Date());
        activityLog.setSignTime(new Date());
        activityLog.setCodeValue(activity.getCodeValue());
        activityLog.setUsername(user.getNickname()+":"+user.getRealName());
        activityLog.setPhone(user.getPhone());
//        activityLog.setOrderId()
        //todo  增加商品规格和用户订单的校验，校验用户是否购买该商品、是否在签到时间范围内、签到地点等
        save(activityLog);
        // 增加record
        UserIntegralRecord userIntegralRecord = integralRecordInit(activityLog, user.getIntegral());
        integralRecordService.save(userIntegralRecord);
        userService.operationIntegral(user.getUid(), activityLog.getCodeValue()
                , user.getIntegral(), "add");

        return data;
    }

    /**
     * 积分添加记录
     *
     * @return UserIntegralRecord
     */
    private UserIntegralRecord integralRecordInit(ActivityLog activityLog, Integer balance) {
        UserIntegralRecord integralRecord = new UserIntegralRecord();
        integralRecord.setUid(activityLog.getUid());
        integralRecord.setLinkId(activityLog.getId().toString());
        integralRecord.setLinkType(IntegralRecordConstants.INTEGRAL_RECORD_LINK_TYPE_ACTIVITY);
        integralRecord.setType(IntegralRecordConstants.INTEGRAL_RECORD_TYPE_ADD);
        integralRecord.setTitle(IntegralRecordConstants.BROKERAGE_RECORD_TITLE_TASK);
        integralRecord.setIntegral(activityLog.getCodeValue());
        integralRecord.setBalance(balance);
        integralRecord.setMark(StrUtil.format("用户完成任务,订单增加{}积分", activityLog.getCodeValue()));
        integralRecord.setStatus(IntegralRecordConstants.INTEGRAL_RECORD_STATUS_COMPLETE);
        integralRecord.setFrozenTime(0);
        integralRecord.setCreateTime(com.zbkj.common.utils.DateUtil.nowDateTime());
        return integralRecord;
    }

    private boolean isSign(Activity activity, User user) {
        LambdaQueryWrapper<ActivityLog> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ActivityLog::getActivityId, activity.getId());
        lqw.eq(ActivityLog::getUid, user.getUid());
        int count = dao.selectCount(lqw);
        if (count > 0) {
            return true;
        }
        return false;
    }

    public static Double getDistance(String latitude, String longitude
            , String latitude1, String longitude1) {
        GlobalCoordinates targetOne = new GlobalCoordinates(Double.parseDouble(latitude)
                , Double.parseDouble(longitude));
        GlobalCoordinates targetTwo = new GlobalCoordinates(Double.parseDouble(latitude1),
                Double.parseDouble(longitude1));
        GeodeticCurve geodeticCurve = new GeodeticCalculator().calculateGeodeticCurve(Ellipsoid.Sphere
                , targetOne, targetTwo);

        return geodeticCurve.getEllipsoidalDistance();
    }
}

